home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / apilot.lha / APilot / APilot_Ser / serial.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-03  |  10.5 KB  |  410 lines

  1. /**************************************************************************
  2.  *
  3.  * serial.c -- Serial routines.
  4.  *
  5.  *-------------------------------------------------------------------------
  6.  * Authors: Casper Gripenberg  (casper@alpha.hut.fi)
  7.  *          Kjetil Jacobsen    (kjetilja@stud.cs.uit.no)
  8.  *
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <time.h>
  14. #include <exec/types.h>
  15. #include <devices/serial.h>
  16.  
  17. #include <proto/dos.h>
  18. #include <proto/exec.h>
  19.  
  20. #include "common.h"
  21. #include "serial.h"
  22.  
  23. #include "main_protos.h"
  24. #include "fuelpod_protos.h"
  25. #include "points_protos.h"
  26.  
  27. extern int sina[];
  28. extern int cosa[];
  29.  
  30. static BOOL   deviceopen = FALSE; 
  31. static struct MsgPort  *SerialMP = NULL;
  32. static struct IOExtSer *SerialIO = NULL;
  33.  
  34. extern AWorld World;
  35.  
  36. /*
  37.  * init_connection -- Opens the serial device and tries to
  38.  *                    agree with the remote site on who should
  39.  *                    be 'host'.
  40.  */
  41. void
  42. init_connection(void)
  43. {
  44.   UBYTE local_randnum  = 0;
  45.   UBYTE remote_randnum = 0;
  46.  
  47.   /*
  48.    * Set the random seed for determining who will be 'host'.
  49.    */
  50.   srand((unsigned int)time(NULL));
  51.  
  52.   if ( SerialMP = CreatePort(0,0) ) {
  53.     if ( SerialIO = (struct IOExtSer *)
  54.          CreateExtIO(SerialMP, sizeof(struct IOExtSer)) ) {
  55.  
  56.       SerialIO->io_SerFlags |= SERF_XDISABLED;
  57.  
  58.       if ( OpenDevice(prefs.ser_dev, prefs.ser_unitnr, 
  59.                       (struct IORequest *)SerialIO, 0) == 0 ) {
  60.         deviceopen = TRUE;
  61.         printf("Serial device open.\n");
  62.         printf("Sizeof(ShipData) = %d\n", sizeof(ShipData));
  63.  
  64.         /*
  65.          * Set parameters...
  66.          */
  67.         SerialIO->IOSer.io_Command = SDCMD_SETPARAMS;
  68.         SerialIO->io_Baud          = prefs.ser_bps;
  69.         SerialIO->io_SerFlags     |= SERF_XDISABLED;
  70.         DoIO((struct IORequest *)SerialIO);
  71.  
  72.         /*
  73.          * Wait a few secs so the other side has time
  74.          * to init.
  75.          */
  76.         Delay(5*50);
  77.  
  78.         /*
  79.          * Start a loop until both agree who will be the
  80.          * host.
  81.          */
  82.         while (local_randnum == remote_randnum) {       
  83.  
  84.           local_randnum = (UBYTE)(rand() % 255);
  85.  
  86.           /*
  87.            * Send the number..
  88.            */
  89.           SerialIO->IOSer.io_Command = CMD_WRITE;
  90.           SerialIO->IOSer.io_Length  = 1;
  91.           SerialIO->IOSer.io_Data    = (APTR)&local_randnum;
  92.           DoIO((struct IORequest *)SerialIO);
  93.  
  94.           /*
  95.            * Read the number..
  96.            */
  97.           SerialIO->IOSer.io_Command = CMD_READ;
  98.           SerialIO->IOSer.io_Length  = 1;
  99.           SerialIO->IOSer.io_Data    = (APTR)&remote_randnum;
  100.           DoIO((struct IORequest *)SerialIO);
  101.         }
  102.  
  103.         printf("Local number : %d\n", local_randnum);
  104.         printf("Remote number: %d\n", remote_randnum);
  105.  
  106.         /*
  107.          * The one with the higher number gets to be host.
  108.          */
  109.         if (local_randnum > remote_randnum) {
  110.           printf("I'm host.\n");
  111.           World.host = TRUE;          
  112.         } else {
  113.           printf("Remote is host.\n");
  114.           World.host = FALSE;
  115.         }
  116.         return;
  117.       }
  118.       cleanExit( RETURN_WARN, "** Unable to open '%s' for communication.\n",
  119.                  prefs.ser_dev );
  120.     }
  121.   }
  122.   cleanExit( RETURN_WARN, "** Unable to init serial device structures.\n" );
  123. }
  124.  
  125.  
  126. /*
  127.  * update_remote -- Reads data from the remote player.
  128.  *                  Updates the ship position, angle, fireing and exhaust.
  129.  *
  130.  *         Returns: TRUE if remote side decided to quit.
  131.  */
  132. BOOL
  133. update_remote( UWORD buf, UWORD nframes )
  134. {
  135.   int i;
  136.   int isin, icos;
  137.  
  138.   ShipData remotedata;
  139.   AShip *ship = World.remote_ship;
  140.  
  141.   WaitIO((struct IORequest *)SerialIO);
  142.  
  143.   SerialIO->IOSer.io_Command = CMD_READ;
  144.   SerialIO->IOSer.io_Length  = sizeof(ShipData);
  145.   SerialIO->IOSer.io_Data    = (APTR)&remotedata;
  146.   DoIO((struct IORequest *)SerialIO);
  147.  
  148.   if (remotedata.chksum != (abs(remotedata.flags + 
  149.                                 remotedata.delta_x + remotedata.delta_y + 
  150.                                 remotedata.xvel + remotedata.yvel) % 250)) {
  151.  
  152.     if (remotedata.flags & REMOTE_QUIT)
  153.       return TRUE;
  154.  
  155.     printf("** Error!! Checksum mismatch!\n");
  156.     return FALSE;
  157.   }
  158.  
  159.   if (remotedata.flags & REMOTE_QUIT)
  160.     return TRUE;
  161.  
  162.   ship->thrusting = FALSE;
  163.   ship->fireing   = FALSE;
  164.   ship->shields   = FALSE;
  165.   ship->fueling   = FALSE;
  166.  
  167.   if (remotedata.flags & SH_THRUSTING)
  168.     ship->thrusting = TRUE;
  169.   if (remotedata.flags & SH_FIREING)
  170.     ship->fireing = TRUE;
  171.   if (ship->turning != YES) {
  172.     ship->turning = NO;
  173.     if (remotedata.flags & SH_LEFTTURN)
  174.       ship->turning = LEFT;
  175.     if (remotedata.flags & SH_RIGHTTURN)
  176.       ship->turning = RIGHT;
  177.   }
  178.   if (remotedata.flags & SH_SHIELDING)
  179.     ship->shields = TRUE;
  180.   if (remotedata.flags & SH_FUELING)
  181.     ship->fueling = TRUE;
  182.  
  183.   /*
  184.    * Check if ship exploded 
  185.    */
  186.   if (ship->status > 0)
  187.     return FALSE;
  188.  
  189.   if (ship->turning != NO || ship->thrusting || ship->fireing) {
  190.  
  191.     if (ship->turning == RIGHT) {
  192.       ship->angle = (ship->angle + ship->rotspeed * nframes) % 360;
  193.     } else if (ship->turning == LEFT) {
  194.       ship->angle = (ship->angle - ship->rotspeed * nframes) % 360;
  195.      }
  196.  
  197.     if (ship->angle < 0)
  198.       ship->angle = 360 + ship->angle;
  199.  
  200.     isin = sina[ship->angle];
  201.     icos = cosa[ship->angle];
  202.  
  203.     if (ship->turning != NO) {
  204.       if (ship->turning == YES) ship->turning = NO;
  205.       /* Rotate the points */
  206.       for(i = 0; i < ship->shapesize; i++) {
  207.         ship->currc[i].x = (ship->shape[i].x * icos - ship->shape[i].y * isin) >> SHFTPR;
  208.         ship->currc[i].y = (ship->shape[i].x * isin + ship->shape[i].y * icos) >> SHFTPR;
  209.       }
  210.     }
  211.   }
  212.  
  213.   for (i = nframes; i > 0; i--) {
  214.     if (ship->thrusting && ship->fuel > 0) {
  215.       ship->xvel += (isin * ship->power) >> SHFTPR;
  216.       ship->yvel -= (icos * ship->power) >> SHFTPR;
  217.     }
  218.     ship->yvel += World.gravity;
  219.     ship->xcount += ship->xvel;
  220.     ship->ycount += ship->yvel;
  221.   }
  222.  
  223.   /* Move ship */
  224.   ship->pos.x += remotedata.delta_x;
  225.   ship->pos.y += remotedata.delta_y;
  226.  
  227.   ship->xvel = remotedata.xvel;
  228.   ship->yvel = remotedata.yvel;
  229.  
  230.   if (ship->thrusting && ship->fuel > 0) {
  231.     add_exhaust(ship, isin, icos, nframes);
  232.     ship->fuelcount += (nframes << 1);
  233.   }
  234.  
  235.   if (ship->fireing) {
  236.     ship->fireing = FALSE;
  237.     if (!ship->shields && ship->fuel > 0) {
  238.       /* Every bullet grabs one fuel */
  239.       ship->fuel -= ship->fw_nbul + ship->bw_nbul;
  240.       add_bullets(ship, isin, icos);
  241.     }
  242.   }
  243.  
  244.   if (ship->shields)
  245.     ship->fuelcount += nframes;
  246.   if (ship->fuelcount >= 50) {
  247.     ship->fuelcount = 0;
  248.     ship->fuel--;
  249.   }
  250.   if (ship->fuel <= 0) {
  251.     ship->shields = FALSE;
  252.     ship->fuel = 0;
  253.   }
  254.  
  255.   if (ship->fueling)
  256.     fuel_ship(ship);
  257.  
  258.   return FALSE;
  259. }
  260.  
  261.  
  262. void
  263. send_local(UWORD nframes)
  264. {
  265.   int i;
  266.   int isin, icos;
  267.   AShip *ship = World.local_ship;
  268.  
  269.   /*
  270.    * This data has to be static when using SendIO(), otherwise
  271.    * when this function exits the data disappears before the serial
  272.    * device has had time to send it.
  273.    */
  274.   static ShipData shipdata;
  275.  
  276.   int xvel = ship->xvel;
  277.   int yvel = ship->yvel;
  278.   int angle = ship->angle;
  279.   int xcount = ship->xcount;
  280.   int ycount = ship->ycount;
  281.   int new_posx = ship->pos.x;
  282.   int new_posy = ship->pos.y;
  283.  
  284.   if (ship->status > 0) {
  285.     shipdata.xvel = 0;
  286.     shipdata.yvel = 0;
  287.     shipdata.flags = 0;
  288.     shipdata.delta_x = 0;
  289.     shipdata.delta_y = 0;
  290.  
  291.     shipdata.chksum = (abs(shipdata.flags + 
  292.                            shipdata.delta_x + shipdata.delta_y + 
  293.                            shipdata.xvel + shipdata.yvel) % 255);
  294.  
  295.     SerialIO->IOSer.io_Command = CMD_WRITE;
  296.     SerialIO->IOSer.io_Length  = sizeof(ShipData);
  297.     SerialIO->IOSer.io_Data    = (APTR)&shipdata;
  298.     SendIO((struct IORequest *)SerialIO);
  299.  
  300.     return;
  301.   }
  302.     
  303.   /*
  304.    * Precalculate the next position so that we can send it
  305.    * while the screen is updated.
  306.    *
  307.    * This is really kludgy, but I couldn't come up with any
  308.    * other way....
  309.    */
  310.   if (ship->turning != NO || ship->thrusting) {
  311.  
  312.     if (ship->turning == RIGHT) {
  313.       angle = (angle + ship->rotspeed * nframes) % 360;
  314.     } else if (ship->turning == LEFT) {
  315.       angle = (angle - ship->rotspeed * nframes) % 360;
  316.     }
  317.  
  318.     if (angle < 0)
  319.       angle = 360 + angle;
  320.  
  321.     isin = sina[angle];
  322.     icos = cosa[angle];
  323.   }
  324.  
  325.   for (i = nframes; i > 0; i--) {
  326.     if (ship->thrusting && ship->fuel > 0) {
  327.       xvel += (isin * ship->power) >> SHFTPR;
  328.       yvel -= (icos * ship->power) >> SHFTPR;
  329.     }
  330.     yvel += World.gravity;
  331.     xcount += xvel;
  332.     ycount += yvel;
  333.   }
  334.  
  335.   /* Move ship */
  336.   new_posx += (xcount < 0) ? -((-xcount) >> SHFTPR) : (xcount >> SHFTPR);
  337.   new_posy += (ycount < 0) ? -((-ycount) >> SHFTPR) : (ycount >> SHFTPR);
  338.  
  339.   if (new_posx >= MAP_BLOCKSIZE*World.Width) {
  340.     new_posx = MAP_BLOCKSIZE*World.Width-1;
  341.     xvel = -(xvel >> 1);
  342.   } else if (new_posx < 0) {
  343.     new_posx = 0;
  344.     xvel = -(xvel >> 1);
  345.   }
  346.   if (new_posy >= MAP_BLOCKSIZE*World.Height) {
  347.     new_posy = MAP_BLOCKSIZE*World.Height-1;
  348.     yvel = -(yvel >> 1);
  349.   } else if (new_posy < 0) {
  350.     new_posy = 0;
  351.     yvel = -(yvel >> 1);
  352.   }
  353.  
  354.   /*
  355.    * Calculate the deltas...
  356.    */
  357.   shipdata.delta_x = (BYTE) (new_posx - ship->pos.x);
  358.   shipdata.delta_y = (BYTE) (new_posy - ship->pos.y);
  359.  
  360.   shipdata.xvel = (WORD)xvel;
  361.   shipdata.yvel = (WORD)yvel;
  362.  
  363.   shipdata.flags = 0;
  364.   if (ship->thrusting) shipdata.flags |= SH_THRUSTING;
  365.   if (ship->fireing)   shipdata.flags |= SH_FIREING;
  366.   if (ship->shields)   shipdata.flags |= SH_SHIELDING;
  367.   if (ship->fueling)   shipdata.flags |= SH_FUELING;
  368.   if (ship->turning == LEFT)  shipdata.flags |= SH_LEFTTURN;
  369.   if (ship->turning == RIGHT) shipdata.flags |= SH_RIGHTTURN;
  370.  
  371.   shipdata.chksum = (abs(shipdata.flags + 
  372.                          shipdata.delta_x + shipdata.delta_y + 
  373.                          shipdata.xvel + shipdata.yvel) % 250);
  374.  
  375.   SerialIO->IOSer.io_Command = CMD_WRITE;
  376.   SerialIO->IOSer.io_Length  = sizeof(ShipData);
  377.   SerialIO->IOSer.io_Data    = (APTR)&shipdata;
  378.   SendIO((struct IORequest *)SerialIO);
  379. }
  380.  
  381. void
  382. send_quit(void)
  383. {
  384.   ShipData quitpacket;
  385.   
  386.   quitpacket.flags = REMOTE_QUIT;
  387.   quitpacket.delta_x = 0;
  388.   quitpacket.delta_y = 0;
  389.   quitpacket.xvel = 0;
  390.   quitpacket.yvel = 0;
  391.   quitpacket.chksum = REMOTE_QUIT;
  392.  
  393.   SerialIO->IOSer.io_Command = CMD_WRITE;
  394.   SerialIO->IOSer.io_Length  = sizeof(ShipData);
  395.   SerialIO->IOSer.io_Data    = (APTR)&quitpacket;
  396.   DoIO((struct IORequest *)SerialIO);
  397. }
  398.  
  399. void
  400. close_connection(void)
  401. {
  402.   if (deviceopen) {
  403.     AbortIO((struct IORequest *)SerialIO);
  404.     WaitIO((struct IORequest *)SerialIO);
  405.     CloseDevice((struct IORequest *)SerialIO);
  406.   }
  407.   if (SerialIO)   DeleteExtIO((struct IORequest *)SerialIO);
  408.   if (SerialMP)   DeletePort(SerialMP);
  409. }
  410.